package com.robusta.spreadsheet.describe.jaxb;

import com.google.common.base.Predicate;
import com.robusta.spreadsheet.describe.ColumnInfo;
import com.robusta.spreadsheet.describe.TemplateInfo;
import com.robusta.spreadsheet.describe.WorksheetInfo;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import java.util.List;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getFirst;
import static java.util.Collections.emptyList;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType
public class Worksheet implements WorksheetInfo {
    @XmlElement(namespace = "http://www.robusta-inc.com/describe-workbook")
    private Template template;
    @XmlElement(namespace = "http://www.robusta-inc.com/describe-workbook")
    private Columns columns; 

    public Template getTemplate() {
        return template;
    }
    
    public List<Column> columns() {
        if(this.columns != null) {
            return this.columns.getColumns();
        }
        return emptyList();
    }

    public TemplateInfo templateInfo() {
        return template;
    }

    public List<? extends ColumnInfo> columnsInfo() {
        return columns();
    }

    @Override
    public ColumnInfo keyColumn() {
        checkState(columns != null, "A minimum of 1 column is required to be described");
        return columns.keyColumn();
    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType
    public static class Columns {
        @XmlElement(name = "column", namespace = "http://www.robusta-inc.com/describe-workbook")
        private List<Column> columns;

        public List<Column> getColumns() {
            return columns;
        }

        public Column keyColumn() {
            checkState(columns != null && !columns.isEmpty(), "A minimum of 1 column is required to be described");
            return getFirst(filter(columns, new Predicate<Column>() {
                @Override
                public boolean apply(Column input) {
                    return input.isKey();
                }
            }), getFirst(columns, null));
        }
    }
}
